package com.kaching.twitter

import twitter4j._
import twitter4j.{User => TUser}
import com.google.appengine.api.datastore._
import javax.jdo._
import gae.client._
import gae.client.KcClient._
import com.kaching.api.client.model._

object KCActor {

  def act(twitter: Twitter, pm : PersistenceManager, stat: TwitterMessage) : KcResponse = getOrLinkUser(twitter, pm, stat) match {
    case kcUser if(kcUser.kcKey == null) => checkKachingLink(kcUser, twitter, pm, stat)
    case kcUser => doKachingAct(kcUser, twitter, pm, stat)
  }
  
  private def getOrLinkUser(twitter: Twitter, pm : PersistenceManager, stat: TwitterMessage) : KCUser = getKachingUser(pm, stat.sender) match {
    case None => linkUser(pm, twitter, stat.sender)
    case Some(kcUser) => kcUser
  }    
  
  private def linkUser(pm : PersistenceManager, twitter: Twitter, user: TUser) : KCUser = {
    try{
      twitter.createFriendship(user.getId.toString, true)
    } catch {
      case e: TwitterException if(e.getMessage.contains("is already on your list")) => //ignore me 
      case other: Throwable => throw other
    }
    println("following user " + user)
    persistUser(pm, user)
  }
  
  val LinkRequest = """[ ]*(\d+)[ ]+([a-zA-Z0-9]+)[ ]*""".r
  
  private def checkKachingLink(kcUser: KCUser, twitter: Twitter, pm : PersistenceManager, stat: TwitterMessage) : KcResponse = stat.text match {
    case LinkRequest(id, key) => persistUserKcLink(java.lang.Integer.parseInt(id), key, kcUser, twitter, pm, stat)
    case _ => LinkResquest(kcUser)
  }

  private def doKachingAct(kcUser: KCUser, twitter: Twitter, pm : PersistenceManager, stat: TwitterMessage) : KcResponse = stat.text match {
    case LinkRequest(id, key) => persistUserKcLink(java.lang.Integer.parseInt(id), key, kcUser, twitter, pm, stat)
    case Order(order) => doOrder(order, kcUser) 
    case _ => ErrorResponse(stat.text)
  }
  
  private implicit def toTuple(property: OrderProperties) = (property.key, property.name)
   
  private def doOrder(order: KcOrder, kcUser: KCUser) : OrderResponse = {
    val post = new UserPost(kcUser, """/portfolio/orders""", 
        Map(order.orderType, 
            order.action,
            orderQuantityName -> order.amount.toString,
            orderSymbolName -> order.symbol))
    OrderResponse(post.actOrder, kcUser)
  }
  
  private def persistUserKcLink(kcId: Long, kcKey: String, kcUser: KCUser, twitter: Twitter, pm: PersistenceManager, stat: TwitterMessage) = {
    kcUser.kcId = kcId
    kcUser.kcKey = kcKey
    pm.makePersistent(kcUser)
    println("persisted user KcLink " + kcUser)
    LinkSuccessResponse(kcUser)
  }
   
  private def persistUser(pm : PersistenceManager, user: TUser) : KCUser = {
    val kcUser = new KCUser(KeyFactory.createKey(classOf[KCUser].getSimpleName(), KCUser.getKeyByTwitterId(user.getId)),
      user.getId,
      user.getScreenName,
      user.getName)
    pm.makePersistent(kcUser)
    println("stored KCUser = " + kcUser)
    kcUser
  }
  
  private def getKachingUser(pm : PersistenceManager, user: TUser) = {
    try {
      val kcUser = pm.getObjectById(classOf[KCUser], KCUser.getKeyByTwitterId(user.getId))
      println("got KCUser = " + kcUser)
      Some(kcUser)
    }
    catch{
      case onf: JDOObjectNotFoundException => {
        println("did not find kcUser of twitter user " + user.getId)
        None
      }
      case e: Throwable => throw e
    }
  }
}